package com.freewater.parking.infrastructure.query;

import com.freewater.parking.infrastructure.db.ParkingViewDao;
import com.freewater.parking.infrastructure.db.ParkingViewTable;
import com.freewater.parking.domain.common.DomainEventListener;
import com.freewater.parking.domain.common.DomainEvent;
import com.freewater.parking.domain.parking.CheckedInEvent;
import com.freewater.parking.domain.parking.CheckedOutEvent;
import com.freewater.parking.domain.parking.PaidEvent;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
@Transactional
public class ParkingViewMaterializer implements DomainEventListener {

    private final ParkingViewDao parkingViewDao;

    public ParkingViewMaterializer(ParkingViewDao parkingViewDao) {
        this.parkingViewDao = parkingViewDao;
    }

    @Override
    public void onEvent(DomainEvent event) {
        if (event instanceof CheckedInEvent checkedInEvent) {
            this.inertParkingRecord(checkedInEvent);
        } else if (event instanceof CheckedOutEvent checkedOutEvent) {
            this.updateOnCheckedOut(checkedOutEvent);
        } else if (event instanceof PaidEvent paidEvent) {
            this.updateOnPaid(paidEvent);
        }
    }

    private void inertParkingRecord(CheckedInEvent checkedInEvent) {
        ParkingViewTable parkingViewTable = new ParkingViewTable();
        parkingViewTable.setPlateNumber(checkedInEvent.getPlateNumber().getValue());
        parkingViewTable.setCheckInTime(checkedInEvent.getCheckInTime());
        this.parkingViewDao.save(parkingViewTable);
    }

    private void updateOnCheckedOut(CheckedOutEvent checkedOutEvent) {
        ParkingViewTable parkingViewTable =
                this.parkingViewDao.findByPlateNumberAndCheckInTime(
                        checkedOutEvent.getPlateNumber().getValue(),
                        checkedOutEvent.getCheckInTime()
                );
        parkingViewTable.setCheckOutTime(checkedOutEvent.getCheckOutTime());
        this.parkingViewDao.save(parkingViewTable);
    }

    private void updateOnPaid(PaidEvent paidEvent) {
        ParkingViewTable parkingViewTable =
                this.parkingViewDao.findByPlateNumberAndCheckInTime(
                        paidEvent.getPlateNumber().getValue(),
                        paidEvent.getCheckInTime()
                );
        this.parkingViewDao.updatePaidAmountAndLastPaidTimeById(parkingViewTable.getId(),
                paidEvent.getAmount(), paidEvent.getPayTime());
    }
}
